package com.putao.job;

import com.dangdang.ddframe.job.api.ShardingContext;
import com.dangdang.ddframe.job.api.simple.SimpleJob;
import com.putao.domain.Job;
import com.putao.domain.SysUser;
import com.putao.feign.UserFeign;
import com.putao.result.JsonResult;
import com.putao.service.JobService;
import com.putao.utils.SnowflakeConfig;
import com.putao.utils.StringUtils;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;


/*
 @Author:putao
 @Date:2021-11-30 11:45:19
*/
@Component
@Getter
@Setter
@Slf4j
public class IncreaseDayJob implements SimpleJob {

    // 0 0/1 * * * ?
    // 0/5 * * * * ?
    @Value("${jobCron.increaseDay}")
    private String cron;

    @Autowired
    private UserFeign userFeign;
    @Autowired
    private JobService jobService;

    @Autowired
    private SnowflakeConfig snowflakeConfig;

    @Override
    public void execute(ShardingContext shardingContext) {
        doWork(shardingContext.getShardingParameter());
    }

    private void doWork(String time) {
        long startTime = new Date().getTime();
        Job job = new Job();
        job.insertInit(snowflakeConfig.snowflakeId());
        job.setDescribes("通过多线程批量修改用户的记账总天数");
        job.setCron(cron);
        // 查出所有的用户，根据个数分成几批。然后使用线程池去执行update方法，然后等待全部执行完后插入一条记录到定时任务表中
        JsonResult<List<SysUser>> userResult = userFeign.getUsers();
        if (userResult.isSuccess()) {
            List<CompletableFuture<JsonResult>> futureList = new ArrayList<>();
            List<SysUser> userList = userResult.getData();
            userList.forEach(user -> {
                user.setConsecutiveBkDays(user.getConsecutiveBkDays() + 1);
                user.updateInit();
            });
            List<List<SysUser>> newUserList = groupListByQuantity(userList, 10);
            for (int i = 0; i < newUserList.size(); i++) {
                int finalI = i;
                futureList.add(CompletableFuture.supplyAsync(() -> {
                    // 增加天数
                    List<SysUser> users = newUserList.get(finalI);
                    return userFeign.increaseDays(users);
                }));
            }
            CompletableFuture.allOf(futureList.toArray(new CompletableFuture[0])).join();
            for (CompletableFuture<JsonResult> future : futureList) {
                try {
                    JsonResult jsonResult = future.get();
                    if (!jsonResult.isSuccess()) {
                        job.setResult(Job.JOB_RESULT_FAIL);
                        break;
                    }
                } catch (InterruptedException | ExecutionException e) {
                    throw new RuntimeException(e);
                }
            }
            if (StringUtils.isBlank(job.getResult())) {
                job.setResult(Job.JOB_RESULT_SUCCESS);
            }
            long endTime = new Date().getTime();
            double seconds = (endTime - startTime) / 1000.0;
            job.setSpendTime(seconds + Strings.EMPTY);
            log.error("总花费时间为 " + seconds + "秒");
            jobService.save(job);
        }
    }

    /**
     * 采用线程池去执行
     * @param time
     */
    private void doWork1(String time) {
        Job job = new Job();
        job.insertInit(snowflakeConfig.snowflakeId());
        job.setDescribes("通过多线程批量修改用户的记账总天数");
        job.setCron(cron);
        ExecutorService executorService = Executors.newCachedThreadPool();
        CompletionService<JsonResult> completionService = new ExecutorCompletionService<>(executorService);
        JsonResult<List<SysUser>> userResult = userFeign.getUsers();
        if (!userResult.isSuccess()) {
            return;
        }
        List<SysUser> userList = userResult.getData();
        long startTime = System.currentTimeMillis();
        int count = 0;
        for (SysUser sysUser : userList) {
            count++;
            GetContentTask getContentTask = new GetContentTask(sysUser, userFeign);
            completionService.submit(getContentTask);
        }
        try {
            // 做完事情要结果
            for (int i = 0; i < count; i ++) {
                Future<JsonResult> resultFuture = completionService.take();
                JsonResult jsonResult = resultFuture.get();
                if (!jsonResult.isSuccess()) {
                    job.setResult(Job.JOB_RESULT_FAIL);
                    break;
                }
                log.error(resultFuture.get() + "");
            }
            long endTime = System.currentTimeMillis();
            long spendTime = (endTime - startTime) / 10000;
            job.setSpendTime(spendTime + Strings.EMPTY);
            log.error("总花费时间为 " + spendTime + "秒");
            jobService.save(job);
        }  catch (Exception ex) {
            ex.printStackTrace();
            log.error(ex.getMessage());
        }
    }

    /**
     * 将集合按指定数量分组
     *
     * @param list     数据集合
     * @param quantity 分组数量
     * @return 分组结果
     */
    public static <T> List<List<T>> groupListByQuantity(List<T> list, int quantity) {

        if (list == null || list.size() == 0) {
            return null;
        }
        if (quantity <= 0) {
            throw new IllegalArgumentException("Wrong quantity.");
        }
        List<List<T>> wrapList = new ArrayList<List<T>>();
        int count = 0;
        while (count < list.size()) {
            wrapList.add(new ArrayList<T>(list.subList(count, Math.min((count + quantity), list.size()))));
            count += quantity;
        }

        return wrapList;
    }

    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("1212");
        List<List<String>> lists = groupListByQuantity(list, 2);
        log.error("lists = " + lists);
    }
}
